package com.yzy.domain.strategy.service.rule.tree.factory.engine.impl;

import java.util.List;
import java.util.Map;


import com.yzy.domain.strategy.model.valobj.RuleLogicCheckTypeVO;
import org.apache.commons.lang3.ObjectUtils;

import com.yzy.domain.strategy.model.valobj.RuleTreeNodeLineVO;
import com.yzy.domain.strategy.model.valobj.RuleTreeNodeVO;
import com.yzy.domain.strategy.model.valobj.RuleTreeVO;
import com.yzy.domain.strategy.service.rule.tree.ILogicTreeNode;
import com.yzy.domain.strategy.service.rule.tree.factory.DefaultTreeFactory;
import com.yzy.domain.strategy.service.rule.tree.factory.DefaultTreeFactory.TreeActionEntity;
import com.yzy.domain.strategy.service.rule.tree.factory.engine.IDecisionTreeEngine;

import lombok.extern.slf4j.Slf4j;

/**
 * @author yangzhenyu05 <yangzhenyu05@kuaishou.com>
 * Created on 2024-01-27
 * @description 决策树引擎
 */
@Slf4j
public class DecisionTreeEngine implements IDecisionTreeEngine {
    private final Map<String, ILogicTreeNode> logicTreeNodeGroup;
    private final RuleTreeVO ruleTreeVO;

    public DecisionTreeEngine(Map<String, ILogicTreeNode> logicTreeNodeGroup, RuleTreeVO ruleTreeVO) {
        this.ruleTreeVO = ruleTreeVO;
        this.logicTreeNodeGroup = logicTreeNodeGroup;
    }

    @Override
    public DefaultTreeFactory.StrategyAwardVO process(String userId, Long strategyId, Integer awardId) {
        DefaultTreeFactory.StrategyAwardVO strategyAwardData = null;
        // 获取基础信息
        String nextNode = ruleTreeVO.getTreeRootRuleNode();
        Map<String, RuleTreeNodeVO> treeNodeMap = ruleTreeVO.getTreeNodeMap();
        RuleTreeNodeVO ruleTreeNode = treeNodeMap.get(nextNode);
        // 循环处理树节点
        while (ObjectUtils.isNotEmpty(nextNode)) {
            // 获取决策节点
            ILogicTreeNode logicTreeNode = logicTreeNodeGroup.get(ruleTreeNode.getRuleKey());
            String ruleValue = ruleTreeNode.getRuleValue();

            // 决策节点计算
            TreeActionEntity logicEntity = logicTreeNode.logic(userId, strategyId, awardId, ruleValue);
            RuleLogicCheckTypeVO ruleLogicCheckTypeVO = logicEntity.getRuleLogicCheckType();
            strategyAwardData = logicEntity.getStrategyAwardVO();
            log.info("决策树引擎【{}】 treeId：{} node：{} code：{}", ruleTreeVO.getTreeName(), ruleTreeVO.getTreeId(),
                    nextNode, ruleLogicCheckTypeVO.getCode());

            // 获取下一个节点
            nextNode = nextNode(logicEntity.getRuleLogicCheckType().getCode(), ruleTreeNode.getTreeNodeLineVOList());
            ruleTreeNode = treeNodeMap.get(nextNode);
        }
        // 返回最终结果
        return strategyAwardData;
    }

    private String nextNode(String matterValue, List<RuleTreeNodeLineVO> ruleTreeNodeLineVOS) {
        if (ObjectUtils.isEmpty(ruleTreeNodeLineVOS)) {
            return null;
        }
        return ruleTreeNodeLineVOS.stream()
                .filter(nodeLine -> decisionLogic(matterValue, nodeLine))
                .findFirst()
                .map(RuleTreeNodeLineVO::getRuleNodeTo)
                .orElseThrow(() -> new RuntimeException("决策树引擎，nextNode 计算失败，未找到可执行节点"));
    }

    public boolean decisionLogic(String matterValue, RuleTreeNodeLineVO nodeLineVO) {
        return switch (nodeLineVO.getRuleLimitType()) {
            case EQUAL -> matterValue.equals(nodeLineVO.getRuleLimitValue().getCode());
            case GT -> false;
            case LT -> false;
            case GE -> false;
            case LE -> false;
            case ENUM -> false;
            default -> false;
        };
    }
}
